iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Software Development

SQL rookie 之天天魯一下系列 第 20

Day 20 - Active Record Query Interface: SQL Injection

  • 分享至 

  • xImage
  •  

Hello, everyone~~

昨天練習了利用Active Record Query Interface 與SQL statements 來query 的方法,今天想趁機試試此前很常看到的SQL injection~~

SQL injection 是什麼呢?Rails Guide是這麼解釋的:
SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data.

**翻譯蒟蒻:SQL injection 是藉著污染傳入query 語句內的params 來操弄資料庫的行為

我們來跟著試試看:

# pure string 寫法
irb(main):006:0> Post.where("body = 'IThome1'")

# params 寫法:
irb(main):017:0> params = { body: "IThome1" }

irb(main):014:0> Post.where("body = ?", params[:body])
  Post Load (0.9ms)  SELECT "posts".* FROM "posts" WHERE (body = 'IThome1')

上面的寫法是比較安全的,但若使用string interpolation 也能得到同樣結果:

irb(main):016:0> Post.where("body = '#{params[:body]}'")
  Post Load (0.7ms)  SELECT "posts".* FROM "posts" WHERE (body = 'IThome1')

然而這種寫法就容易導致SQL injection:

# 同上的params
params = { body: "IThome1" }

# 在application 上帶入params 時,大多會有id 欄位的資料連同被回傳
params = params.merge(id: 1)

# 此時若id params 被污染了
params[:id] = "1) OR 1=1--"

# query 就會回傳不該出現的資料
Post.where("id = #{params[:id]}")

# here
irb(main):010:0> Post.where("id = #{params[:id]}").count
   (0.8ms)  SELECT COUNT(*) FROM "posts" WHERE (id = 1) OR 1=1--)
100

可從上述最後一個query statement 和結果筆數看到全部資料都被叫出來了,若這時搭配的方法是delete_by就真的掰了:

irb(main):010:0> Post.delete_by("id = #{params[:id]}")
  Post Destroy (0.7ms)  DELETE FROM "posts" WHERE (id = 1) OR 1=1--)
100

# 或
irb(main):011:0> post = Post.where("id = #{params[:id]}")
irb(main):012:0> post.update(title: "SQL injection badbad")

但為什麼1) OR 1=1--"會影響那麼大呢?

這可以分成幾個部分理解:
1): 即強迫完成了前句的query:Post.where("id = 1)")
OR: 或是
1=1: 因前句(id = 1) 為true 加上或是1=1 為true,則每一筆資料都被選取了
--: SQL 的註解符號,即無效化後方的statement,就藉機排除了syntax error

即:SELECT COUNT(*) FROM "posts" WHERE (id = 1) OR 1=1--)
所以追中才會導致每筆資料都被選起來處理啦~~

雖然SQL injection 要剛好遇到可被污染的情境(欄位、語句)及方法(如query 的欄位形態 + delete_by vs. delete),可會做這種事的大大功力應該不容小覷,若server 恰巧沒驗證阻擋或沒預警管理員,屆時可能為時已晚啦~

那今天就先研究到這裡囉,謝謝大家~~

參考資料:
Rails 實作 SQL Injection | wells's blog
4. SQL Injection 資料庫注入攻擊 - Rails 實戰聖經
Rails SQL Injection Examples
Rails SQL Injection Guide: Examples and Prevention


上一篇
Day 19 - Active Record Query Interface(2)
下一篇
Day 21 - Active Record Query Interface: group method(1)
系列文
SQL rookie 之天天魯一下30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言